#include "../include/client.h"
#include "../../command/command.h"
//----------------------------------------

typedef struct pthreadIdArr_s{
    int idArr[1024];
    int size;
}pthreadIdArr_t;
typedef struct pthreadArg_s{
    char token[1024];
    int cmdType;
    char cmdArg[128];
    struct sockaddr_in* paddr;
    socklen_t addrLen;
    char userName[1024];
}pthreadArg_t;

int pthreadIdArrInit(pthreadIdArr_t *childIdArr){
    if(childIdArr == NULL){
        return -1;
    }
    for(int i = 0; i < 1024; i++){
        childIdArr->idArr[i] = -1;
    }
    childIdArr->size = 0;
    return 0;
}
int pthreadArgInit(pthreadArg_t *childArg){
    if(childArg == NULL){
        return -1;
    }

    childArg->token[0] = '\0';
    childArg->cmdType = 0;
    childArg->cmdArg[0] = '\0';
    childArg->paddr = NULL;
    childArg->addrLen = 0;
    childArg->userName[0] = '\0';
    return 0;
}
//  登录代码
void register_fun(int sockfd, pthreadArg_t *childArg){
    char prompt[1024] = {0};
    char input[1024] = {0};
    //  接收服务端发送“1.登录 2.注册”
    recv(sockfd, prompt, sizeof(prompt), 0);
    printf("%s",prompt);
    scanf("%s",input);
    send(sockfd, input, strlen(input), MSG_NOSIGNAL);
    bzero(input, sizeof(input));
    //  接收服务端提示输入用户名称提示
    bzero(prompt,sizeof(prompt));
    recv(sockfd, prompt, sizeof(prompt), 0);
    printf("%s",prompt);
    scanf("%s",input);
    strcpy(childArg->userName, input);
    send(sockfd, input, strlen(input), MSG_NOSIGNAL);
    bzero(input, sizeof(input));

    //  接收服务端提示输入用户密码提示
    bzero(prompt,sizeof(prompt));
    recv(sockfd, prompt, sizeof(prompt), 0);
    printf("%s",prompt);
    scanf("%s",input);
    send(sockfd, input, strlen(input), MSG_NOSIGNAL);
    bzero(input, sizeof(input));


    recv(sockfd, prompt, sizeof(prompt),0);
    printf("%s", prompt);

}
void* childFunc(void* arg){
    pthreadArg_t* Arg = (pthreadArg_t*)arg;
    int tempSockfd =socket(AF_INET,SOCK_STREAM,0);
    int ret =connect(tempSockfd,(struct sockaddr *)Arg->paddr,Arg->addrLen);
    ERROR_CHECK(ret,-1,"connect");
    // 给服务端发文件类型
    /* int isConnect = 1; */
    /* send(tempSockfd, &isConnect, sizeof(int), MSG_NOSIGNAL); */
    int isConnect = 1;
    send(tempSockfd, &isConnect, sizeof(int), MSG_NOSIGNAL);
    //  发用户名
    printf("before send\n");
    int usernameLen = strlen(Arg->userName)+1;
    send(tempSockfd,&usernameLen,sizeof(int),0);
    send(tempSockfd, Arg->userName, usernameLen, MSG_NOSIGNAL);
    printf("userName:%s\n",Arg->userName);
    // 建立连接后先发送token
    printf("Arg,token:|%s|\n",Arg->token);
    /* sendToken(tempSockfd,Arg->token); */
    int tokenLen = strlen(Arg->token)+1;
    send(tempSockfd,&tokenLen,sizeof(int),0);
    send(tempSockfd,Arg->token,tokenLen,0);       

    printf("send token \n");
    // 收一个token，占位，收到的token为空时，说明token校验正确
    printf("before recv token \n");
    /* recvToken(tempSockfd,Arg->token); */
    printf("------DEBUG1\n");
    int check;
    recv(tempSockfd, &check, sizeof(int), MSG_WAITALL);
    printf("check token:%d\n",check);
    printf("------DEBUG2\n");
    if(check == -1){
        printf("token 错误\n");
        pthread_exit(NULL);
    }
    printf("------DEBUG3\n");
    int pathId;
    recv(tempSockfd,&pathId,sizeof(int),MSG_WAITALL);
    printf("recv pathId %d\n",pathId);
    // 发GETS或者PUTS 先不考虑token错的情况 --------
    //
    char hash_name[1024] = {0};
    int fret = fileContentHash_sha256(Arg->cmdArg,hash_name);
    /* if(fret == -1){ */
    /*     sendCmd(sockfd,"-1",-1); */
    /*     break; */
    /* } */
    int speedTransFlag = 0;
    sendCmd_p(tempSockfd,hash_name,Arg->cmdType,&pathId);

    if(Arg->cmdType == PUTS){
        /* printf("send file name |%s|\n",Arg->cmdArg); */
        Arg->cmdArg[strlen(Arg->cmdArg)-1] = '\0';
        printf("send file name |%s|\n",Arg->cmdArg);
        sendFile(tempSockfd,Arg->cmdArg,Arg->cmdArg,ret);
    }   
    if(Arg->cmdType == GETS){// modify 3
        char buf[4096]={0};
        bzero(buf,sizeof(buf));
        recvFile(tempSockfd,buf,&Arg->cmdType);
    }
    // 执行结束，关闭连接
    close(tempSockfd);
    return NULL;
}
//--------------------------------------------------



int main(int argc, char *argv[]){                                  
    // client.c 192.168.. 12345
    ARGS_CHECK(argc,3);
    int sockfd =socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[2]));
    addr.sin_addr.s_addr=inet_addr(argv[1]);
    int ret =connect(sockfd,(struct sockaddr *)&addr,sizeof(addr));
    ERROR_CHECK(ret,-1,"connect");
    //创建epoll
    int epfd=epoll_create(1);
    epollAdd(epfd,STDIN_FILENO);
    epollAdd(epfd,sockfd);
    char buf[4096] = {0}; 
    char dest_cmd[4096] = {0};
    char real_cmd[4096] = {0};
    int flag = 0;
    struct epoll_event readyset[1024];

    //-----------------------------
    // pthread id arr
    pthreadIdArr_t childIdArr;
    pthreadIdArrInit(&childIdArr);
    // save token cmd cmdArg in a struct 
    pthreadArg_t childArg;
    pthreadArgInit(&childArg);
    printf("--------------\n");
    // 给服务端发命令类型
    int isConnect = 0;
    send(sockfd, &isConnect, sizeof(int), MSG_NOSIGNAL);
    if(isConnect == 0){
        register_fun(sockfd,&childArg);
    }
    // 客户端本地保存pathId
    int pathId;
    recv(sockfd, &pathId, sizeof(int), MSG_WAITALL);
    // 收服务端发的token
    char token[1024] = {0};
    /* recvToken(sockfd, token); */
    int tokenLen = 0;
    recv(sockfd,&tokenLen,sizeof(int),MSG_WAITALL);
    recv(sockfd,token,tokenLen,MSG_WAITALL);
    printf("recv token|%s|\n",token);
    // 指令
    while(1){
        printf(">>:"); // >>: LS 
        fflush(stdout);
        int readynum =epoll_wait(epfd,readyset,1024,-1);
        for(int i =0;i < readynum;i++){
            if(readyset[i].data.fd == STDIN_FILENO){
                bzero(buf,sizeof(buf));
                bzero(dest_cmd,sizeof(dest_cmd));
                bzero(real_cmd,sizeof(real_cmd));
                read(STDIN_FILENO,buf,sizeof(buf));
                int ret = splitCommand(buf,dest_cmd);
                if(ret == -1){
                    continue;
                }
                //--------------------------------------
                // if input long command
                delSpace(dest_cmd,real_cmd);// modify 1
                if(ret == PUTS||ret == GETS){
                    childArg.cmdType=ret;
                    strncpy(childArg.cmdArg,real_cmd,128);// 128 need a #define
                    strncpy(childArg.token,token,strlen(token)+1);
                    childArg.paddr = &addr;
                    childArg.addrLen = sizeof(addr);
                    pthread_t tid;
                    pthread_create(&tid,NULL,childFunc,&childArg);
                    childIdArr.idArr[childIdArr.size++] = tid;
                    continue;
                }
                //--------------------------------------
                /* delSpace(dest_cmd,real_cmd);// modify 1 */
                sendCmd_p(sockfd,real_cmd,ret,&pathId);
                /* if(ret == PUTS){// modify2 */
                /*     real_cmd[strlen(real_cmd)-1] = '\0'; */
                /*     sendFile(sockfd,real_cmd,real_cmd,ret); */
                /* } */
            }
            else{   
                printf("--------------\n");
                bzero(&flag,sizeof(flag));
                bzero(buf,sizeof(buf));
                recvCmd_p(sockfd,buf,&flag,&pathId);
                /* if(flag == GETS){// modify 3 */
                /*     bzero(buf,sizeof(buf)); */
                /*     recvFile(sockfd,buf,&flag); */
                /* } */
                printf("%s\n",buf);
                if(flag == 0){
                    close(sockfd);
                    return -1;
                }
            }       
        }
    }
    return 0;
}
